package com.hyw.trace.configuration.meta;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;

/**
 * 采样器的抽象定义
 * <p>
 * 考虑到采集器布点过多,采集器的创建频繁会带来大量的性能问题和内存的频繁分配,故需要保证采集器是<b>线程安全(ThreadSafe)</b>的, 以便于框架做采集器实例的缓存
 * 
 * @author hongyu
 * @param <T>
 *          泛型载体
 */
public abstract class TraceSampler<T> {
  private static final Logger log = LoggerFactory.getLogger(TraceSampler.class);

  protected Class<T> type;

  @SuppressWarnings("unchecked")
  public TraceSampler() {
    this.type = (Class<T>) getClass();
    log.debug("采集器初始化:{}", type);
  }

  /**
   * 针对 params入参要做以下特殊说明: <br>
   * 如果 params为Object,则默认会从参数列表中获取第一个对象进行填充 <br>
   * 如果 params为Object[], 则默认会将整个参数列表打包成数组对象进行填充 <br>
   * 如果 params为具体的某个子类,则默认会遍历参数列表, 并将获取的第一个期望类型的参数进行填充 <br>
   * 对于以上几个步骤,比如参数列表为空, 或者, 参数列表不为空但找不到期望的具体子类的, 则会抛出异常: {@link IllegalArgumentException} <br>
   * <b>如果sampler的拦截结果是来自于方法执行之后的结果作为入参,则(T)只能永远是Object类型,切记</b>
   * 
   * @param params
   *          入参由子类决定 , 一般由框架上层会根据期望值对参数进入注入
   * @return 对于收集器的结果而言,最好的方式就是key-value的形式, key永远为字符串, 则value则允许是字符\数值\布尔\枚举常量等.<br>
   *         对于{@link TraceEvent}的properties非空是必然判断的. 如果为空, 则默认抛弃该事件.即如果该方法的返回值为<b>empty(null or size is Zero)</b>,则消息会被抛弃
   */
  public abstract @Nullable Map<String, ?> process(T params);

}